#ifndef numuCCPXSelection_h
#define numuCCPXSelection_h

#include "SelectionBase.hxx"
#include "Parameters.hxx"

//TODO: has to be changed later t nd280Samples::kFGD1NuMuCCPX
const nd280Samples::SampleEnum gkSampleEnumCCPX = nd280Samples::kFGD1NuMuCCQE;

class numuCCPXSelection: public SelectionBase{
 public:
  numuCCPXSelection(bool forceBreak=true);
  virtual ~numuCCPXSelection(){}

  //---- These are mandatory functions
  void DefineSteps();
  inline AnaBoxB* MakeBox();
  bool FillEventSummary(const AnaBoxB& box, AnaEventB& event, Int_t allCutsPassed[]);

  nd280Samples::SampleEnum GetSampleEnum(){return gkSampleEnumCCPX;}
};

class AnaBoxCCPX: public AnaBoxB{

public:

  AnaBoxCCPX() {
    MuonCandidate = ProtonCandidate = NULL;
  }  
  virtual ~AnaBoxCCPX(){}

  std::vector<AnaTrackB*> TrackerTracks;

  /// For storing tracks with TPC information in the bunch.
  std::vector<AnaTrackB*> TPCtracks;
  std::vector<AnaTrackB*> NegativeTPCtracksOutFV;
  std::vector<AnaTrackB*> PositiveTPCtracksOutFV;
  std::vector<AnaTrackB*> BadQuaTPCtracksInFV;
  std::vector<AnaTrackB*> BadQuaTPCtracksOutFV;

  /// For storing tracks with FGD information in the bunch.
  std::vector<AnaTrackB*> FGDtracks;
  std::vector<AnaTrackB*> FGDtracksCrossingFGD1;
  std::vector<AnaTrackB*> FGDtracksInFGD1Volume;
  std::vector<AnaTrackB*> FGDContTracksInFV;
  std::vector<AnaTrackB*> FGDNotContTracksInFV;
  std::vector<AnaTrackB*> FGDContTracksOutFV;
  std::vector<AnaTrackB*> FGDNotContTracksOutFV;

  // neut counters
  int Nmuons;
  int Nprotons;

  AnaTrackB* MuonCandidate;
  AnaTrackB* ProtonCandidate;
};

inline AnaBoxB* numuCCPXSelection::MakeBox() {return new AnaBoxCCPX();}

namespace std_numuccPX_actions{
  void FindTracksWithTPC(const AnaEventB& event, AnaBoxCCPX& box, bool qualityCut = true, SubDetId::SubDetEnum det = SubDetId::kFGD1);
  void FindTracksWithFGDAndNoTPC(const AnaEventB& event, AnaBoxCCPX& box, SubDetId::SubDetEnum det = SubDetId::kFGD1);

  /// Fnd the correct sense of a secondary track by comparing its start and end positions with the vertex
  void FindCorrectSense(AnaTrackB* track, AnaVertexB* vertex);
}

class OneNegativeTrackCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new OneNegativeTrackCut();}
};

class MichelElectronCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new MichelElectronCut();}
};

class TwoTrackerTracksCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new TwoTrackerTracksCut();}
};

class OnePositiveTrackCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new OnePositiveTrackCut();}
};


class ProtonPIDCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new ProtonPIDCut();}
};

class FindMichelElectronsAction: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new FindMichelElectronsAction();}
};

class FindTrackerTracksAction: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new FindTrackerTracksAction();}
};

class FindCorrectProtonSenseAction: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new FindCorrectProtonSenseAction();}
};

  /// Find Muon and Proton candidates for all topologies
class FindCandidatesAction: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new FindCandidatesAction();}
};


//fine to use CCQE Vertex cut
class CommonVertexCut1: public StepBase{
public:
  CommonVertexCut1(){
    _cutX = ND::params().GetParameterI("psycheSelections.numuCCQE.CutX1");
    _cutY = ND::params().GetParameterI("psycheSelections.numuCCQE.CutY1");
    _cutZ = ND::params().GetParameterI("psycheSelections.numuCCQE.CutZ1");
  }
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new CommonVertexCut1();}
private:
  int _cutX;
  int _cutY;
  int _cutZ;
};




#endif
